package redis.inaction.xx.api;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.inaction.xx.entity.UserStatus;
import redis.inaction.xx.service.UserStatusService;
import redis.inaction.xx.utils.ThreadLocalContext;
import redis.inaction.xx.utils.CommonResponse;

import static redis.inaction.xx.utils.ResponseCode.ILLEGAL_ARG;
import static redis.inaction.xx.utils.ResponseCode.INVERNAL_ERROR;

@RestController
@RequestMapping("/xx/userstatus")
@Slf4j
public class UserStatusController {

    @Autowired
    private UserStatusService userStatusService;

    @GetMapping("/get")
    public String getCurrentUserStatus() {
        String userId = ThreadLocalContext.getLoginUserId();
        Long status = userStatusService.getUserStatus(userId);
        return CommonResponse.successResponse(UserStatus.builder().id(new Long(userId)).status(status).build());
    }

    /**
     * 根据状态因子更新用户状态位.
     * 更新"应用"新用户状态 => factor = 1   (1)
     * 更新"收藏"新用户状态 => factor = 10  (2)
     * 更新"领卡"新用户状态 => factor = 100 (4)
     *
     * @param factor 状态因子: 1, 2, 4, 8, 16 ...
     * @return
     */
    @GetMapping("/update")
    public String updateUserStatus(long factor){
        String userId = ThreadLocalContext.getLoginUserId();
        Long status = userStatusService.getUserStatus(userId);
        if(!validateFactor(factor)){
            return CommonResponse.failResponse(ILLEGAL_ARG, "invalid status factor");
        }
        if( (status & factor) == factor ){
            log.info("No need to update status by factor: {}, current status: {}", factor, status);
            return CommonResponse.successResponse();
        }
        status |= factor;
        boolean rt = userStatusService.setUserStatus(userId, status);
        return rt ? CommonResponse.successResponse() : CommonResponse.failResponse(INVERNAL_ERROR, "FAIL");
    }

    /**
     * 状态因子factor 其二进制值 有且只有一位为1，其余位均为0
     *
     * @param factor
     * @return
     */
    private boolean validateFactor(long factor){
        //校验 状态因子
        if( factor <= 0 ){
            return false;
        }
        int count = 0;
        while(factor != 0){
            if( (factor & 1) == 1){
                count++;
            }
            if(count > 1){
                return false;
            }
            factor >>= 1;
        }

        return count == 1;
    }

}
